

DISPLAY_OFFSET	enableLongMode
	cli
	mov	edi,	GdtStart.codeLong
	mov	esi,	GdtLongEntries
	mov	ecx,	3*2
	rep	movsd
	
	mov	edi,	IDT_ADDR
	mov	eax,	DWORD [Idt64.exception]
	mov	edx,	DWORD [Idt64.exception+4]
	xor	ebx,	ebx
	mov	ecx,	19+1
.loop0:
	mov	[edi],	eax
	mov	[edi+4],	edx
	mov	[edi+8],	ebx
	mov	[edi+12],	ebx
	add	edi,	16
	loop	.loop0
	
	mov	eax,	DWORD [Idt64.trap]
	mov	edx,	DWORD [Idt64.trap+4]
	mov	edi,	IDT_ADDR
	mov	[edi+3*16],	eax
	mov	[edi+3*16+4],	edx
	mov	[edi+3*16+8],	ebx
	mov	[edi+3*16+12],	ebx
	mov	[edi+4*16],	eax
	mov	[edi+4*16+4],	edx
	mov	[edi+4*16+8],	ebx
	mov	[edi+4*16+12],	ebx
	
	mov	eax,	DWORD [Idt64.picMaster]
	mov	edx,	DWORD [Idt64.picMaster+4]
	mov	edi,	IDT_ADDR+30h*16
	mov	ecx,	8
.loop1:
	mov	[edi],	eax
	mov	[edi+4],	edx
	mov	[edi+8],	ebx
	mov	[edi+12],	ebx
	add	edi,	16
	loop	.loop1
	
	mov	eax,	DWORD [Idt64.picSlave]
	mov	edx,	DWORD [Idt64.picSlave+4]
	mov	ecx,	8
.loop2:
	mov	[edi],	eax
	mov	[edi+4],	edx
	mov	[edi+8],	ebx
	mov	[edi+12],	ebx
	add	edi,	16
	loop	.loop2
	
	; reserved
	mov	edi,	IDT_ADDR
	mov	[edi+9*16],	ebx
	mov	[edi+9*16+4],	ebx
	mov	[edi+9*16+8],	ebx
	mov	[edi+9*16+12],	ebx
	mov	[edi+15*16],	ebx
	mov	[edi+15*16+4],	ebx
	mov	[edi+15*16+8],	ebx
	mov	[edi+15*16+12],	ebx
	
	xor	eax,	eax
	add	edi,	20*16
	mov	ecx,	4*(30h-20)
	rep	stosd
	
	add	edi,	16*16
	mov	ecx,	4*(256-40h)
	rep	stosd
	
	lidt	FWORD [Idt64Addr]
	mov	ax,	GdtStart.tssLong-GdtStart
	ltr	ax
	
	ret

enterLongMode:
	cli
	lidt	FWORD [Idt64Addr]
	
	mov	BYTE [GdtStart.tssLong+5],	10001001b
	
	mov	ax,	GdtStart.tssLong-GdtStart
	ltr	ax
	
	;call	enablePageIA32e
	mov	edx,	cr0
	bts	edx,	31
	mov	cr0,	edx
	
	pop	DWORD [.returnAddress]
	sti
	jmp	far FWORD [.returnAddress]
.returnAddress:	dd	0, GdtStart.codeLong-GdtStart

USE64
quitLongMode:
	pop	rax
	mov	[.returnAddress],	eax
	jmp	far FWORD [.returnAddress]
.returnAddress:	dd	0, GdtStart.codeAll-GdtStart

Null8259SlaveInterrupt64:
	push	ax
	mov	al,	PIC_EOI
	out	PIC2_COMMAND,	al
	out	PIC1_COMMAND,	al
	pop	ax
	iret
Null8259MasterInterrupt64:
	push	ax
	mov	al,	PIC_EOI
	out	PIC1_COMMAND,	al
	pop	ax
NullCpuInterrupt64:
	iret
	
USE32
ALIGN	4
	dw	0CCCCh, 0CCCCh, 0CCCCh
Idt64Addr:	dw	0FFFh
		dq	IDT_ADDR
GdtLongEntries:
	dw	0FFFFh, 0
	db	0, 10011010b, 10101111b, 0
	; 64-bit Code, Readable, Noncomforming, Not Acccessed
	
	dw	KernelTss64End-KernelTss64-1, KernelTss64
	db	0, 10001001b, 01000000b, 0
	dq	0
	; 64-bit TSS, Readable, Noncomforming, Not Acccessed
Idt64:
.exception:
	dw	die, GdtStart.codeLong-GdtStart
	db	0, 10001110b
	dw	0
	; present, DPL=0, 64-bit interrupt gate
.trap:
	dw	NullCpuInterrupt64, GdtStart.codeLong-GdtStart
	db	0, 10001111b
	dw	0
	; present, DPL=0, 64-bit trap gate
.picMaster:
	dw	Null8259MasterInterrupt64, GdtStart.codeLong-GdtStart
	db	0, 10001110b
	dw	0
	; present, DPL=0, 64-bit interrupt gate
.picSlave:
	dw	Null8259SlaveInterrupt64, GdtStart.codeLong-GdtStart
	db	0, 10001110b
	dw	0
	; present, DPL=0, 64-bit interrupt gate

KernelTss64:
.reserved0:	dd	0
.rsp0:		dq	7C00h
.rsp1:		dq	7C00h
.rsp2:		dq	7C00h
.reserved1:	dq	0
.ist:		dq	7 dup(0)
.reserved2:	dq	0
.iomap:		dw	0, 0FFFFh
KernelTss64End:
